from typing import List, Dict, Any, Tuple, Optional
from tqdm import tqdm
from config import KEEP_SCI_QUARTILES, KEEP_CAS_QUARTILES, REMOVE_UNKNOWN_QUARTILES
from ris_parser import RISParser
from easyscholar_api import EasyScholarAPI

class LiteratureFilter:
    """文献筛选器"""
    
    def __init__(self, api_key: str = None, keep_sci_quartiles: List[str] = None, 
                 keep_cas_quartiles: List[str] = None, remove_unknown: bool = None):
        """
        初始化筛选器
        
        Args:
            api_key: EasyScholar API密钥
            keep_sci_quartiles: 要保留的SCI分区列表
            keep_cas_quartiles: 要保留的中科院分区列表
            remove_unknown: 是否删除无法获取分区信息的文献
        """
        self.api = EasyScholarAPI(api_key)
        self.parser = RISParser()
        
        # 设置筛选条件
        self.keep_sci_quartiles = keep_sci_quartiles if keep_sci_quartiles is not None else KEEP_SCI_QUARTILES
        self.keep_cas_quartiles = keep_cas_quartiles if keep_cas_quartiles is not None else KEEP_CAS_QUARTILES
        self.remove_unknown = remove_unknown if remove_unknown is not None else REMOVE_UNKNOWN_QUARTILES
        
    def filter_literature(self, input_file: str, output_file: str = None, progress_callback=None) -> Tuple[int, int, List[Dict[str, Any]]]:
        """
        筛选文献
        
        Args:
            input_file: 输入RIS文件路径
            output_file: 输出RIS文件路径，如果不提供则自动生成
            progress_callback: 进度回调函数，接收(当前进度, 消息)参数
            
        Returns:
            (原始文献数量, 筛选后文献数量, 筛选后的文献列表)
        """
        if progress_callback:
            progress_callback(10, f"正在解析RIS文件: {input_file}")
        else:
            print(f"开始解析RIS文件: {input_file}")
        
        # 解析输入文件
        entries = self.parser.parse_ris_file(input_file)
        if not entries:
            if progress_callback:
                progress_callback(100, "未找到任何文献条目")
            else:
                print("未找到任何文献条目")
            return 0, 0, []
        
        original_count = len(entries)
        if progress_callback:
            progress_callback(20, f"共找到 {original_count} 篇文献，开始筛选...")
        else:
            print(f"共找到 {original_count} 篇文献")
        
        # 筛选文献
        filtered_entries = self._filter_entries(entries, progress_callback)
        filtered_count = len(filtered_entries)
        
        if progress_callback:
            progress_callback(80, f"筛选完成: {original_count} -> {filtered_count} 篇文献")
        else:
            print(f"筛选完成: {original_count} -> {filtered_count} 篇文献")
            print(f"删除了 {original_count - filtered_count} 篇文献")
        
        # 生成输出文件名
        if not output_file:
            output_file = self._generate_output_filename(input_file)
        
        # 写入输出文件
        if progress_callback:
            progress_callback(90, "正在保存筛选结果...")
            
        if self.parser.write_ris_file(filtered_entries, output_file):
            if progress_callback:
                progress_callback(100, f"筛选结果已保存到: {output_file}")
            else:
                print(f"筛选结果已保存到: {output_file}")
        else:
            if progress_callback:
                progress_callback(100, "保存文件时出错")
            else:
                print("保存文件时出错")
        
        return original_count, filtered_count, filtered_entries
    
    def _filter_entries(self, entries: List[Dict[str, Any]], progress_callback=None) -> List[Dict[str, Any]]:
        """
        筛选文献条目
        
        Args:
            entries: 原始文献条目列表
            progress_callback: 进度回调函数
            
        Returns:
            筛选后的文献条目列表
        """
        filtered_entries = []
        
        if progress_callback:
            progress_callback(25, "开始查询期刊分区信息...")
        else:
            print("开始查询期刊分区信息...")
        
        for i, entry in enumerate(entries):
            # 更新进度
            if progress_callback:
                progress = 25 + int((i / len(entries)) * 50)  # 25% 到 75%
                progress_callback(progress, f"正在筛选第 {i+1}/{len(entries)} 篇文献...")
            
            # 提取期刊信息
            journal_info = self.parser.extract_journal_info(entry)
            
            # 查询期刊分区信息
            quartile_info = self.api.get_journal_info(journal_info)
            
            # 判断是否保留该文献
            if self._should_keep_entry(entry, quartile_info):
                filtered_entries.append(entry)
            else:
                # 打印被删除的文献信息
                title = entry.get('TI', entry.get('T1', '未知标题'))
                journal = journal_info.get('title', '未知期刊')
                sci_q = quartile_info.get('jcr_quartile', '未知') if quartile_info else '未知'
                cas_q = quartile_info.get('cas_quartile', '未知') if quartile_info else '未知'
                
                delete_msg = f"删除: {title[:50]}... (期刊: {journal}, SCI: {sci_q}, 中科院: {cas_q})"
                if progress_callback:
                    progress_callback(progress, delete_msg)
                else:
                    print(delete_msg)
        
        return filtered_entries
    
    def _should_keep_entry(self, entry: Dict[str, Any], quartile_info: Optional[Dict[str, Any]]) -> bool:
        """
        判断是否应该保留该文献条目
        
        Args:
            entry: 文献条目
            quartile_info: 分区信息
            
        Returns:
            是否保留该文献
        """
        if not quartile_info:
            # 如果无法获取分区信息，根据设置决定是否保留
            title = entry.get('TI', entry.get('T1', '未知标题'))
            if self.remove_unknown:
                warning_msg = f"删除: 无法获取期刊分区信息: {title[:50]}..."
                print(warning_msg)
                return False
            else:
                warning_msg = f"保留: 无法获取期刊分区信息: {title[:50]}..."
                print(warning_msg)
                return True
        
        # 检查SCI分区
        sci_quartile = quartile_info.get('jcr_quartile')  # API返回的字段名仍然是jcr_quartile
        cas_quartile = quartile_info.get('cas_quartile')
        
        # 如果SCI分区在保留列表中，则保留
        if sci_quartile and sci_quartile in self.keep_sci_quartiles:
            return True
        
        # 如果中科院分区在保留列表中，则保留
        if cas_quartile and cas_quartile in self.keep_cas_quartiles:
            return True
        
        # 如果两个条件都不满足，则删除
        title = entry.get('TI', entry.get('T1', '未知标题'))
        delete_msg = f"删除: {title[:50]}... (SCI: {sci_quartile or '未知'}, 中科院: {cas_quartile or '未知'})"
        print(delete_msg)
        return False
    
    def _generate_output_filename(self, input_file: str) -> str:
        """
        生成输出文件名
        
        Args:
            input_file: 输入文件路径
            
        Returns:
            输出文件路径
        """
        from pathlib import Path
        from config import OUTPUT_SUFFIX
        
        # 使用Path对象处理路径
        input_path = Path(input_file)
        base_name = input_path.stem
        extension = input_path.suffix
        
        # 生成新文件名
        output_file = input_path.parent / f"{base_name}{OUTPUT_SUFFIX}{extension}"
        
        # 如果文件已存在，添加数字后缀
        counter = 1
        while output_file.exists():
            output_file = input_path.parent / f"{base_name}{OUTPUT_SUFFIX}_{counter}{extension}"
            counter += 1
        
        return str(output_file)
    
    def get_filtering_stats(self, entries: List[Dict[str, Any]]) -> Dict[str, Any]:
        """
        获取筛选统计信息
        
        Args:
            entries: 文献条目列表
            
        Returns:
            统计信息字典
        """
        stats = {
            'total_entries': len(entries),
            'sci_q1': 0,
            'sci_q2': 0,
            'sci_q3': 0,
            'sci_q4': 0,
            'sci_unknown': 0,
            'cas_q1': 0,
            'cas_q2': 0,
            'cas_q3': 0,
            'cas_q4': 0,
            'cas_unknown': 0,
            'no_info': 0
        }
        
        for entry in entries:
            journal_info = self.parser.extract_journal_info(entry)
            quartile_info = self.api.get_journal_info(journal_info)
            
            if not quartile_info:
                stats['no_info'] += 1
                continue
            
            # 统计SCI分区
            sci_q = quartile_info.get('jcr_quartile')
            if sci_q:
                stats[f'sci_{sci_q.lower()}'] += 1
            else:
                stats['sci_unknown'] += 1
            
            # 统计中科院分区
            cas_q = quartile_info.get('cas_quartile')
            if cas_q:
                stats[f'cas_{cas_q.lower()}'] += 1
            else:
                stats['cas_unknown'] += 1
        
        return stats 